package com.train.generator;

import com.train.common.utils.date.LocalDateTimeUtils;
import com.train.generator.utils.DbUtil;
import com.train.generator.utils.Field;
import com.train.generator.utils.FreemarkerUtil;
import freemarker.template.TemplateException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.util.*;

@Slf4j
public class ServerGenerator {

    private static String servicePath = "train-booking-platform-[module]/train-booking-platform-[module]-biz/src/main/java/com/train/[module]/";
    private static final String pomPath = "train-booking-platform-infra/train-booking-platform-generator/pom.xml";

    private static String vuePath = "web/src/views/";

    private static String module = "";

//    private static final ArrayList<Object> enumValues;

    public static void main(String[] args) throws Exception {
        // pom中获取获取mybatis-generator路径
        String generatorPath = getGeneratorPath();
        log.info(generatorPath);

        //获取业务模块名
        module = generatorPath.replace("src/main/resources/generator-config-", "")
                .replace(".xml", "");
        log.info(module);

        //替换servicePath路径下的[module]
        servicePath = servicePath.replace("[module]", module);
        log.info(servicePath);

        // 读取table节点和它的tableName、domainObjectName属性名
        Document document = new SAXReader().read("train-booking-platform-infra/train-booking-platform-generator/" + generatorPath);
        Node table = document.selectSingleNode("//table");
        Node tableName = table.selectSingleNode("@tableName");
        Node domainObjectName = table.selectSingleNode("@domainObjectName");
        log.info(tableName.getText() + "/" + domainObjectName.getText());

        // 初始化数据源
        Node jdbcConnection = document.selectSingleNode("//jdbcConnection");
        Node conn = jdbcConnection.selectSingleNode("@connectionURL");
        Node userId = jdbcConnection.selectSingleNode("@userId");
        Node password = jdbcConnection.selectSingleNode("@password");
        DbUtil.url = conn.getText();
        DbUtil.password = password.getText();
        DbUtil.user = userId.getText();
        log.info(conn.getText() + "/" + userId.getText() + "/" + password.getText());

        List<Field> fields = DbUtil.getColumnByTableName(tableName.getText()); //获取字段信息
        String tableNameCn = DbUtil.getTableComment(tableName.getText()); //获取表中文名
        Set<String> javaTypes = getJavaTypes(fields); //转java类型

        //格式化模块业务名
        String Domain = domainObjectName.getText(); //首字母大写
        String domain = Domain.substring(0, 1).toLowerCase() + Domain.substring(1); //全小写
        String DOMAIN = Domain.toUpperCase(); //全大写
        //把table_name替换成tbale-name
        String domain_main = tableName.getText().replace("_", "-"); //下划线替换成横线

        //替换类或接口参数
        Map<String, Object> params = new HashMap<>();
        params.put("Domain", Domain);
        params.put("domain", domain);
        params.put("DOMAIN", DOMAIN);
        params.put("domain_main", domain_main);
        params.put("module", module);

        //替换实体对象参数
        params.put("tableNameCn", tableNameCn);
        params.put("fieldList", fields);
        params.put("typeSet", javaTypes);
        params.put("tableName", tableName.getText());

        //注释参数
        params.put("date", LocalDateTimeUtils.getNowStr(LocalDateTimeUtils.DATE_TIME_FORMAT));
        params.put("author", "baitiaojun");

        log.info(servicePath + Domain + "ServiceImpl.java");

        //生成模版
        process(Domain, params, "/service/impl/", "serviceImpl");
        process(Domain, params, "/service/", "service");
        process(Domain, params, "/facade/", "facadeImpl");
        process(Domain, params, "/facade/", "facade");
        process(Domain, params, "/req/", "addOrEditReq");
        process(Domain, params, "/req/", "pageReq");
        process(Domain, params, "/resp/", "pageResp");
        process(Domain, params, "/po/", "PO");
        process(Domain, params, "/dto/", "pageDTO");
        process(Domain, params, "/dto/", "addOrEditDTO");
        process(Domain, params, "/mapper/", "mapper");
        process(Domain, params, "/mapper/", "mapperxml");
        process(domain, params); //vue模版
    }

    /**
     * 生成模版
     * @param domain
     * @param params
     * @param packageName
     * @param target
     * @throws IOException
     * @throws TemplateException
     */
    private static void process(String domain, Map<String, Object> params, String packageName, String target) throws IOException, TemplateException {
        String toPath = servicePath + packageName;

        //初始化模版
        FreemarkerUtil.initConfig(target + ".ftl");

        //创建toPath路径
        File file = new File(toPath);
        if (!file.exists()) {
            file.mkdirs();
        }

        //首字母转大写
        target = target.substring(0, 1).toUpperCase() + target.substring(1);

        //全路径名=路径+业务模块名+目标名+扩展名
        String fileName = "";
        if ("Mapperxml".equals(target)) {
            fileName = toPath + domain + target.replace("xml", "") + ".xml";
        } else {
            fileName = toPath + domain + target + ".java";
        }
        log.info(fileName);

        FreemarkerUtil.generator(fileName, params);
    }

    @SneakyThrows
    private static void process(String domain, Map<String, Object> params) {
        //初始化模版
        FreemarkerUtil.initConfig( "vue.ftl");
        //拼接全路径
        String fileName = vuePath + module + "/" + domain + "/" + "Index.vue";
        log.info("生成: " + fileName);
        //创建fileName路径
        File file = new File(vuePath + module + "/" + domain);
        if (!file.exists()) {
            file.mkdirs();
        }
        FreemarkerUtil.generator(fileName, params);
    }

    /**
     * pom中获取xml文件路径
     * @return
     * @throws DocumentException
     */
    private static String getGeneratorPath() throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Map<String, String> map = new HashMap<String, String>();
        map.put("pom", "http://maven.apache.org/POM/4.0.0");
        saxReader.getDocumentFactory().setXPathNamespaceURIs(map);
        Document document = saxReader.read(pomPath);
        Node node = document.selectSingleNode("//pom:configurationFile");
        return node.getText();
    }

    /**
     * 获取所有的Java类型，使用Set去重
     */
    private static Set<String> getJavaTypes(List<Field> fieldList) {
        Set<String> set = new HashSet<>();
        for (int i = 0; i < fieldList.size(); i++) {
            Field field = fieldList.get(i);
            set.add(field.getJavaType());
        }
        return set;
    }




//    static {
//        enumValues = new ArrayList<>();
//        for (String className : enumClassNames) {
//            try {
//                Class<?> enumClass = Class.forName(className);
//                if (enumClass.isEnum()) {
//                    Method valuesMethod = enumClass.getMethod("values");
//                    Object[] values = (Object[]) valuesMethod.invoke(null);
//                    enumValues.addAll(Arrays.asList(values));
//                } else {
//                    log.warn("Class {} is not an enum", className);
//                }
//            } catch (ClassNotFoundException e) {
//                log.error("Class not found: {}", className, e);
//            } catch (Exception e) {
//                log.error("Error loading enum class: {}", className, e);
//            }
//        }
//    }
}
